grammar smal;

@header{
package org.javanile.smal.parser;
import org.javanile.smal.engine.Engine;
}
@lexer::header {
package org.javanile.smal.parser;
}
@members {
Engine engine = new Engine();
}

main	: list* EOF			{engine.exit();}
	;
		
list	: boot '(' ')' 			{engine.push(engine.name($boot.text));engine.push(engine.void());}
	| boot '(' head ')'		{engine.push(engine.name($boot.text));engine.push(engine.void());}	
	| boot '(' head tail ')'	{engine.push(engine.name($boot.text));engine.push(engine.void());}
	;

boot 	: 'define'
	| 'select'
	| ID
	;
	
head	: ID
	;
	
tail	: ID
	;
	
ID  	: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
	;

INT 	: '0'..'9'+
    	;	

FLOAT	: ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    	| '.' ('0'..'9')+ EXPONENT?
    	| ('0'..'9')+ EXPONENT
    	;

COMMENT : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    	| '***' ( options {greedy=false;} : . )* '***' {$channel=HIDDEN;}
    	;

WS	: (' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    	;

STRING	: '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    	;

CHAR	: '\'' ( ESC_SEQ | ~('\''|'\\') ) '\''
    	;

fragment
EXPONENT: ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;
